<template>
  <div class="wxFileUpload" :class="{'wx-no-drag':!drag,'upload-hidden':this.limit===this.fileList.length}">
    <el-upload ref="upload" drag
               :show-file-list="showFileList"
               :multiple="multiple"
               :list-type="isPicture?'picture-card':'text'"
               :file-list="fileList"
               :limit="limit"
               action="#"
               :before-upload="upBeforeValidate"
               :on-exceed="onExceed"
               :http-request="uploadFile">

      <div slot="file" slot-scope="{file}">
        <div v-if="isPicture" style="position: relative">
          <el-image :class="{opacity:fileOpacity(file)}" class="el-upload-list__item-thumbnail"
                    style="width:148px;height:148px;"
                    :src="file.url" fit="contain"/>
          <el-progress v-if="file.loading" :percentage="file.progress" :show-text="false"/>
          <span class="el-upload-list__item-actions">
              <span class="el-upload-list__item-preview" v-if="allowRefresh">
                <i class="el-icon-refresh" @click="refresh(file)"/>
              </span>
              <span class="el-upload-list__item-delete">
                <i class="el-icon-delete" @click="removeFile(file)"></i>
              </span>
            </span>
          <label class="el-upload-list__item-status-label" v-if="!file.loading">
            <i class="el-icon-upload-success el-icon-check"/>
          </label>
        </div>

        <div v-else>
          <ul class="el-upload-list el-upload-list--text">
            <li tabindex="0" class="el-upload-list__item is-success">
              <a class="el-upload-list__item-name">{{ file.name }}</a>
              <label class="el-upload-list__item-status-label">
                <i class="el-icon-upload-success el-icon-circle-check"/>
              </label>
              <i class="el-icon-close" @click="removeFile(file)"/>
              <!--              <i class="el-icon-close-tip">按 delete 键可删除</i>-->
            </li>
          </ul>
        </div>
      </div>

      <slot>
        <div v-if="!isPicture">
          <i class="el-icon-upload"/>
          <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        </div>
        <i v-else class="el-icon-plus avatar-uploader-icon"/>
      </slot>

      <div v-if="tips" slot="tip" class="load-tips">{{ tips }}</div>
    </el-upload>
  </div>
</template>

<script>
import {fileUpValidate, isPictureLoad, uploadFile} from "@/api/wxqy/file";
import {isArray} from "@/utils/validate";

/**
 * @param list {array | string} 回显数据
 *
 * event:
 * @success:成功时的回调,return {name: , url: }
 * @remove:删除的回调,return [url1,url2]  返回剩余文件list
 */
export default {
  name: "wxFileUpload",
  props: {
    multiple: { // 多文件上传
      type: Boolean,
      default: false
    },
    drag: {
      type: Boolean,
      default: false
    },
    showFileList: {
      type: Boolean,
      default: true
    },
    limit: {
      type: Number,
      default: 10
    },
    fileTypes: {
      type: String | Array,
      default: ''
    },
    tips: {
      default: ''
    },
    allowRefresh: {
      type: Boolean,
      default: false
    },
    list: {
      type: Array | String,
      default: () => []
    }
  },
  watch: {
    list: {
      immediate: true,
      handler(v) {
        if (v) {
          this.fileList = isArray(v) ? v : [{url: v}]
        } else {
          this.fileList = []
        }
      }
    }
  },
  data() {
    return {
      isPicture: false,
      index: 0,
      replaceFile: null,
      //[{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}]
      //{url: 'http://file.ycccx.cn/83b46fb0755040a0949b895aa75e447f.png', name: '123.jpg'}
      // fileList: [{url: 'http://file.ycccx.cn/2058423462274c2685b8e7bc145733e9.jpeg', name: '123.jpg'}]
      fileList: []
    }
  },
  methods: {
    findFileOfFileList(fileUid) {
      for (let i = 0; i < this.fileList.length; i++) {
        if (fileUid === this.fileList[i].uid) {
          return i
        }
      }
      return -1
    },
    loadComponentType() {
      this.isPicture = isPictureLoad(this.fileTypes)
    },
    upBeforeValidate(file) {
      let allow = fileUpValidate(file, this.fileTypes, this)
      if (allow) {
        let map = {uid: file.uid, name: file.name, url: '', loading: true, progress: 0}
        if (this.replaceFile) {
          this.uploadFail(file) //删除最后一个展示的
          let index = this.findFileOfFileList(this.replaceFile.uid)
          this.fileList[index] = map
        } else {
          this.fileList.push(map)
        }
      }
      return allow
    },
    onExceed() {
      this.$message.error('超出最大上传个数, 最多可上传' + this.limit + '个')
    },
    fileOpacity(file) {
      return file.loading
    },
    refresh(file) {
      this.replaceFile = file
      this.$refs.upload.$children[1].$el.click()
    },
    removeFile(file) {
      this.fileList = this.fileList.filter(f => f.uid !== file.uid)
      let data = this.fileList.map(f => {
        return {name: f.name, url: f.url}
      })
      this.$emit('remove', data)
    },
    uploadFail(file) {
      let up = this.$refs.upload.uploadFiles
      up.splice(up.indexOf(file), 1)
      this.fileList = this.fileList.filter(f => f.uid !== file.uid)
    },
    uploadFile(file) {
      let f = file.file, onProgress
      let uid = f.uid
      let index = this.findFileOfFileList(uid)
      onProgress = (e) => {
        this.fileList[index].progress = e.loaded / e.total * (80 + Math.round(Math.random()) * 10) | 0
      }
      uploadFile(f, onProgress)
        .then(res => {
          let data = res.data
          if (data && data.files) {
            let urls = data.files
            const info = {name: f.name, url: urls[0]}
            this.fileList[index].url = urls[0]
            this.$set(this.fileList, index, this.fileList[index])
            this.$emit('success', info)
          }
        }).catch(() => {
        this.uploadFail(f)
      }).finally(() => {
        this.fileList[index].loading = false
        this.fileList[index].progress = 100
        this.replaceFile = null
      })
    },
    findData() {
      let data = this.fileList.map(f => {
        return {name: f.name, url: f.url}
      })
      if (data.length) {
        return {success: true, data: data}
      }
      this.$message.error('文件不能为空~')
    }
  },
  created() {
    this.loadComponentType()
  }
}
</script>

<style scoped lang="scss">

.load-tips {
  color: #a8a7a7;
  font-size: 12px;
  line-height: 20px;
  margin-top: 6px;
}

.wx-no-drag {
  ::v-deep.el-upload--text {
    width: 360px;
    height: 180px;
  }

  ::v-deep.el-upload-dragger {
    width: 100%;
    height: 100%;
  }
}

.upload-hidden {
  ::v-deep .el-upload {
    display: none;
  }
}

.opacity {
  opacity: 0.2;
}
</style>
